package com.cekanet.mybudget;


import java.io.IOException;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Locale;


import javax.servlet.http.*;


import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import org.xml.sax.SAXException;

import com.cekanet.mybudget.dbutils.ProtectionException;
import com.cekanet.mybudget.dbutils.StatementHandler;
import com.cekanet.mybudget.dbutils.StatementItem;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserServiceFactory;







@SuppressWarnings("serial")
public class AlterStatementServlet extends HttpServlet {
	public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {

		try {
			boolean isError = false;
			String errorDescription="Unknow error";
			StatementItem statementItem = null;
			try {
				statementItem = this.doRequested(req);
			}catch (RequestParseException e){
				isError=true;
			} catch (UserException e) {
				errorDescription = "Cannot retrive user data in servlet";
				e.printStackTrace();
			} catch (ProtectionException e) {
				errorDescription = "You are not the owner of the record you are attempting to access/modify";
				e.printStackTrace();
			} catch (ParseException e) {
				errorDescription = "Error while reading request. Malformed XML ?";
				e.printStackTrace();
			}

			DocumentBuilderFactory docFactory= DocumentBuilderFactory.newInstance();
			DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

			Document doc = docBuilder.newDocument();
			Element rootElement = doc.createElement("response");
			doc.appendChild(rootElement);


			Element exitStatus = doc.createElement("exitStatus");
			rootElement.appendChild(exitStatus);

			if (isError){
				exitStatus.setAttribute("status", "ERROR");
				Element statDescription = doc.createElement("description");
				exitStatus.appendChild(statDescription);
				statDescription.appendChild(doc.createTextNode(errorDescription));
			}else {
				exitStatus.setAttribute("status", "OK");
				Element statDescription = doc.createElement("description");
				exitStatus.appendChild(statDescription);
				statDescription.appendChild(doc.createTextNode("Job done !"));

				if(statementItem!=null){

					DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");  
					DecimalFormat currencyFormat = new DecimalFormat();
					currencyFormat.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.ITALY));
					currencyFormat.setGroupingUsed(false);
					
					Element item = doc.createElement("item");
					rootElement.appendChild(item);
					item.setAttribute("id",statementItem.getId().toString());

					Element date = doc.createElement("date");
					date.appendChild(doc.createTextNode(dateFormat.format(statementItem.getDate())));
					item.appendChild(date);

					Element price = doc.createElement("price");
					price.appendChild(doc.createTextNode(currencyFormat.format(statementItem.getPrice())));
					item.appendChild(price);

					Element name = doc.createElement("name");
					name.appendChild(doc.createTextNode(statementItem.getName()));
					item.appendChild(name);

					Element description = doc.createElement("description");
					description.appendChild(doc.createTextNode(statementItem.getDescription()));
					item.appendChild(description);
				}


				TransformerFactory transformerFactory = TransformerFactory.newInstance();
				Transformer transformer = transformerFactory.newTransformer();
				DOMSource source = new DOMSource(doc);


				resp.setContentType("text/xml");
				StreamResult result = new StreamResult(resp.getWriter());
				transformer.transform(source, result);

			}
		} catch (ParserConfigurationException e) {

			e.printStackTrace();
		} catch (TransformerConfigurationException e) {

			e.printStackTrace();
		} catch (TransformerException e) {

			e.printStackTrace();
		}

	}

	private void deleteStatementItem(String id) throws UserException, NumberFormatException, ProtectionException{
		User user = UserServiceFactory.getUserService().getCurrentUser();
		if (user == null)
			throw new UserException("User service returned null.");
		
		StatementHandler statementHandler = new StatementHandler(user.getUserId());
		
		statementHandler.deleteStatementItem(new Long(id));

	}
	private StatementItem modifyStatementItem(String id,String date,String price,String name,String description) throws UserException, ProtectionException, ParseException{
		User user = UserServiceFactory.getUserService().getCurrentUser();
		if (user == null)
			throw new UserException("User service returned null.");
		
		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");  
		DecimalFormat currencyFormat = new DecimalFormat();
		currencyFormat.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.ITALY));
		currencyFormat.setGroupingUsed(false);
		
		StatementHandler statementHandler = new StatementHandler(user.getUserId());
		StatementItem statementItem = statementHandler.getItem(new Long(id));
		
		statementItem.setDate(dateFormat.parse(date));
		statementItem.setPrice(new BigDecimal(currencyFormat.parse(price).doubleValue()));
		statementItem.setName(name.trim().toUpperCase());
		statementItem.setDescription(description.trim().toUpperCase());


		return statementHandler.alterItem(statementItem);
	}
	private StatementItem addStatementItem(String date,String price,String name,String description) throws UserException, ProtectionException, ParseException{
		User user = UserServiceFactory.getUserService().getCurrentUser();
		if (user == null)
			throw new UserException("User service returned null.");
		
		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");  
		DecimalFormat currencyFormat = new DecimalFormat();
		currencyFormat.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.ITALY));
		currencyFormat.setGroupingUsed(false);
		
		StatementHandler statementHandler = new StatementHandler(user.getUserId());
		
		return statementHandler.alterItem(new StatementItem(
				dateFormat.parse(date),
				new BigDecimal(currencyFormat.parse(price).doubleValue()),
				name.trim().toUpperCase(),
				description.trim().toUpperCase()
				));
		
		
	}

	private StatementItem doRequested(HttpServletRequest req) throws IOException, RequestParseException, UserException, ProtectionException, ParseException{
		StatementItem statementItem = null;

		try {
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			Document requestDoc = dBuilder.parse(req.getInputStream());
			requestDoc.getDocumentElement().normalize();

			Element requestRootElement = requestDoc.getDocumentElement();
			if (!requestRootElement.getNodeName().equals("request"))
				throw new RequestParseException("Malformed request.");

			String requestedAction = requestRootElement.getAttribute("action");

			Element requestItem = (Element) requestRootElement.getElementsByTagName("item").item(0);
			if(requestedAction.equals("add")){
				statementItem = this.addStatementItem(
						requestItem.getElementsByTagName("date").item(0).getTextContent(),
						requestItem.getElementsByTagName("price").item(0).getTextContent(),
						requestItem.getElementsByTagName("name").item(0).getTextContent(),
						requestItem.getElementsByTagName("description").item(0).getTextContent()
						);
			}else if(requestedAction.equals("modify")){

				statementItem = this.modifyStatementItem(
						requestItem.getAttribute("id"),
						requestItem.getElementsByTagName("date").item(0).getTextContent(),
						requestItem.getElementsByTagName("price").item(0).getTextContent(),
						requestItem.getElementsByTagName("name").item(0).getTextContent(),
						requestItem.getElementsByTagName("description").item(0).getTextContent()
						);

			}else if(requestedAction.equals("delete")){
				this.deleteStatementItem(requestItem.getAttribute("id"));
			} else {
				throw new RequestParseException("Malformed request.");
			}	
		}catch (ParserConfigurationException e) {
			e.printStackTrace();
			throw new RequestParseException("Error.");
		} catch (SAXException e) {
			e.printStackTrace();
			throw new RequestParseException("Error.");
		}
		return statementItem;
	}

}
